package org.asiainfo.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Dict;
import org.asiainfo.common.core.constant.AnnouncementConstants;
import org.asiainfo.common.core.exception.ServiceException;
import org.asiainfo.common.core.utils.DateRangeUtils;
import org.asiainfo.common.core.utils.SpringUtils;
import org.asiainfo.common.core.utils.StringUtils;
import org.asiainfo.common.mybatis.stream.core.page.TableDataInfo;
import org.asiainfo.common.mybatis.stream.core.page.PageQuery;
import org.asiainfo.common.satoken.utils.LoginHelper;
import org.asiainfo.system.domain.SysAnnouncementSend;
import org.asiainfo.system.domain.SysDictData;
import org.asiainfo.system.domain.table.SysAnnouncementSendTableDef;
import org.asiainfo.system.domain.table.SysAnnouncementTableDef;
import org.asiainfo.system.domain.vo.SysAnnouncementVo;
import org.asiainfo.system.domain.bo.SysAnnouncementBo;
import org.asiainfo.system.domain.SysAnnouncement;
import org.asiainfo.system.domain.vo.SysDictDataVo;
import org.asiainfo.system.mapper.SysDictDataMapper;
import org.asiainfo.system.service.SysAnnouncementSendService;
import org.asiainfo.system.service.SysAnnouncementService;
import org.springframework.stereotype.Service;
import org.asiainfo.common.core.utils.MapstructUtils;
import lombok.extern.slf4j.Slf4j;
import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.asiainfo.system.mapper.SysAnnouncementMapper;
import com.mybatisflex.core.paginate.Page;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 系统通告表(SysAnnouncement)表服务实现类
 *
 * @author dotor-ww
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SysAnnouncementServiceImpl extends ServiceImpl<SysAnnouncementMapper, SysAnnouncement> implements SysAnnouncementService {

    private final SysDictDataMapper sysDictDataMapper;

    /**
     * 查询
     *
     * @param sysAnnouncementBo 筛选条件
     * @return 查询结果
     */
    @Override
    public List<SysAnnouncementVo> queryList(SysAnnouncementBo sysAnnouncementBo) {
        Map<String, Object> params = sysAnnouncementBo.getParams();
        QueryWrapper query = query();
        return listAs(query, SysAnnouncementVo.class);
    }

    /**
     * 通过id查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public SysAnnouncementVo queryById(Long id) {
        return getOneAs(query().eq(SysAnnouncement::getId, id), SysAnnouncementVo.class);
    }

    /**
     * 分页查询
     *
     * @param sysAnnouncementBo 筛选条件
     * @param pageQuery         分页对象
     * @return 查询结果
     */
    @Override
    public TableDataInfo<SysAnnouncementVo> queryPageList(SysAnnouncementBo sysAnnouncementBo, PageQuery pageQuery) {
        Map<String, Object> params = sysAnnouncementBo.getParams();
        QueryWrapper query = query().between(SysAnnouncement::getCreateTime, params.get("beginTime"), params.get("endTime"),
            ObjectUtil.isNotNull(params.get("beginTime")) && ObjectUtil.isNotNull(params.get("endTime")));
        pageQuery.buildOrder(query);
        Page<SysAnnouncementVo> page = pageAs(pageQuery.buildPage(), query, SysAnnouncementVo.class);
        return TableDataInfo.build(page);
    }

    /**
     * 新增数据
     *
     * @param sysAnnouncementBo 实例对象
     * @return 实例对象
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean insertByBo(SysAnnouncementBo sysAnnouncementBo) {
        SysAnnouncement sysAnnouncement = MapstructUtils.convert(sysAnnouncementBo, SysAnnouncement.class);
        if (ObjectUtil.isNull(sysAnnouncement)) {
            throw new ServiceException("参数错误");
        }
        boolean status = save(sysAnnouncement);
        if (AnnouncementConstants.MSG_TYPE_USER.equals(sysAnnouncementBo.getMsgType())) {
            List<String> userIds = StringUtils.splitList(sysAnnouncementBo.getUserIds());
            if (CollUtil.isNotEmpty(userIds)) {
                List<SysAnnouncementSend> sysAnnouncementSends = CollUtil.newArrayList();
                Long id = sysAnnouncement.getId();
                Date date = new Date();
                for (String userId : userIds) {
                    SysAnnouncementSend sysAnnouncementSend = new SysAnnouncementSend();
                    sysAnnouncementSend.setAntId(id);
                    sysAnnouncementSend.setUserId(Convert.toLong(userId));
                    sysAnnouncementSend.setReadFlag(AnnouncementConstants.NO_READ_FLAG);
                    sysAnnouncementSend.setReadTime(date);
                    sysAnnouncementSends.add(sysAnnouncementSend);
                }
                SpringUtils.getBean(SysAnnouncementSendService.class).saveBatch(sysAnnouncementSends);
            }
        }
        return status;
    }

    /**
     * 修改数据
     *
     * @param sysAnnouncementBo 实例对象
     * @return 实例对象
     */
    @Override
    public Boolean updateByBo(SysAnnouncementBo sysAnnouncementBo) {
        SysAnnouncement sysAnnouncement = MapstructUtils.convert(sysAnnouncementBo, SysAnnouncement.class);
        if (ObjectUtil.isNotNull(sysAnnouncement)) {
            sysAnnouncement.setSendStatus(AnnouncementConstants.UN_PUBLISH);
        }
        return updateById(sysAnnouncement);
    }

    /**
     * 通过主键删除数据
     *
     * @param ids 主键
     * @return 是否成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return removeByIds(ids);
    }

    /**
     * 发布系统通告
     *
     * @param id 主键ID
     * @return 发布是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean publish(Long id) {
        SysAnnouncement sysAnnouncement = getById(id);
        sysAnnouncement.setId(id);
        sysAnnouncement.setSender(LoginHelper.getUserId());
        sysAnnouncement.setSendStatus(AnnouncementConstants.PUBLISHED);
        sysAnnouncement.setSendTime(new Date());
        boolean status = updateById(sysAnnouncement);
        String msgType = sysAnnouncement.getMsgType();
        if (AnnouncementConstants.MSG_TYPE_ALL.equals(msgType)) {
            SpringUtils.getBean(SysAnnouncementSendService.class).batchInsert(sysAnnouncement.getId(), sysAnnouncement.getTenantId());
            // 推送消息
        } else {
            // 给固定用户推送消息
        }
        // 可拓展推送钉钉、企微
        return status;
    }

    /**
     * 撤销发布
     *
     * @param id 主键ID
     * @return 发布是否成功
     */
    @Override
    public Boolean quash(Long id) {
        SysAnnouncement sysAnnouncement = new SysAnnouncement();
        sysAnnouncement.setId(id);
        sysAnnouncement.setSendStatus(AnnouncementConstants.QUASH);
        sysAnnouncement.setCancelTime(new Date());
        return updateById(sysAnnouncement);
    }

    /**
     * 获取未读消息数量
     *
     * @return 未读消息数量
     */
    @Override
    public Long getUnreadMessageCount() {
        Long userId = LoginHelper.getUserId();
        return queryChain().select()
            .from(SysAnnouncementSend.class)
            .rightJoin(SysAnnouncement.class)
            .on(SysAnnouncementSendTableDef.SYS_ANNOUNCEMENT_SEND.ANT_ID.eq(SysAnnouncementTableDef.SYS_ANNOUNCEMENT.ID))
            .and(SysAnnouncementTableDef.SYS_ANNOUNCEMENT.SEND_STATUS.eq(AnnouncementConstants.PUBLISHED))
            .where(SysAnnouncementSendTableDef.SYS_ANNOUNCEMENT_SEND.USER_ID.eq(userId))
            .and(SysAnnouncementSendTableDef.SYS_ANNOUNCEMENT_SEND.READ_FLAG.eq(0L))
            .count();
    }

    /**
     * 获取未读消息数组信息
     *
     * @return 未读消息数组信息
     */
    @Override
    public Object getUnreadMessageByUserId() {
        Dict dict = Dict.create();
        // 获取上个月第一天
        Date lastMonthStartDay = DateRangeUtils.getLastMonthStartDay();
        // 获取当前用户ID
        Long userId = LoginHelper.getUserId();
        // 获取所有的通知公告类型
        List<SysDictDataVo> sysDictDataVos = sysDictDataMapper.selectListByQueryAs(query().eq(SysDictData::getDictType, AnnouncementConstants.DICT_TYPE_NAME), SysDictDataVo.class);
        // 获取所有的未读消息
        List<Long> antIds = queryChain().select(SysAnnouncementSendTableDef.SYS_ANNOUNCEMENT_SEND.ANT_ID)
            .from(SysAnnouncementSend.class)
            .where(SysAnnouncementSendTableDef.SYS_ANNOUNCEMENT_SEND.USER_ID.eq(userId))
            .and(SysAnnouncementSendTableDef.SYS_ANNOUNCEMENT_SEND.READ_FLAG.eq(AnnouncementConstants.NO_READ_FLAG))
            .and(SysAnnouncementSendTableDef.SYS_ANNOUNCEMENT_SEND.CREATE_TIME.ge(lastMonthStartDay))
            .listAs(Long.class);
        for (SysDictDataVo sysDictDataVo : sysDictDataVos) {
            String dictValue = sysDictDataVo.getDictValue();
            String dictLabel = sysDictDataVo.getDictLabel();
            List<SysAnnouncementVo> sysAnnouncementVos = CollUtil.newArrayList();
            if (CollUtil.isNotEmpty(antIds)) {
                QueryWrapper query = query().select(SysAnnouncementTableDef.SYS_ANNOUNCEMENT.DEFAULT_COLUMNS)
                    .and(SysAnnouncementTableDef.SYS_ANNOUNCEMENT.SEND_STATUS.eq(AnnouncementConstants.PUBLISHED))
                    .and(SysAnnouncementTableDef.SYS_ANNOUNCEMENT.MSG_CATEGORY.eq(dictValue))
                    .and(SysAnnouncementTableDef.SYS_ANNOUNCEMENT.CREATE_TIME.ge(lastMonthStartDay))
                    .and(SysAnnouncementTableDef.SYS_ANNOUNCEMENT.ID.in(antIds));
                // 获取所有的未读消息
                sysAnnouncementVos = listAs(query, SysAnnouncementVo.class);
            }
            dict.put(dictLabel, sysAnnouncementVos);
        }
        return dict;
    }
}
